package com.rbac.web.controller;

import com.rbac.web.exception.ApplicationException;
import com.rbac.web.model.*;
import com.rbac.web.model.req.RoleAddReq;
import com.rbac.web.model.req.RoleGetListReq;
import com.rbac.web.model.req.RolePermissionAddReq;
import com.rbac.web.model.res.RoleGetListRes;
import com.rbac.web.model.res.RoleGetOneRes;
import com.rbac.web.service.IRolePermissionService;
import com.rbac.web.service.IRoleService;
import com.rbac.web.service.IUserRoleService;
import com.rbac.web.service.IUserTokenService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

/**
 * @author gengaoliu
 */
@RestController
@RequestMapping("/role")
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
@Tag(name = "角色管理", description = "刘澳港")
public class RoleController {

  private final IRoleService roleService;
  private final IUserRoleService userRoleService;
  private final IUserTokenService tokenService;
  private final IRolePermissionService rolePermissionService;

  @PostMapping
  @Operation(summary = "添加角色")
  public void saveRole(@RequestBody RoleAddReq req) {
    roleService.insert(req.toDomain());
  }

  @GetMapping("/{id}")
  @Operation(summary = "查看角色")
  public RoleGetOneRes getOneRes(@PathVariable Integer id) {
    return roleService
        .selectById(id)
        .map(RoleGetOneRes::fromDomain)
        .orElseThrow(() -> ApplicationException.createException("不存在的角色"));
  }

  @PutMapping("/{id}")
  @Operation(summary = "修改角色")
  public void update(@PathVariable Integer id, @RequestBody RoleAddReq req) {
    Role role = req.toDomain();
    role.setId(id);
    roleService.update(role);
  }

  @DeleteMapping("/{id}")
  @Operation(summary = "删除角色")
  public void delete(@PathVariable Integer id) {
    roleService.deleteById(id);
    rolePermissionService.deleteAllByRoleId(id);
  }

  @GetMapping
  @Operation(summary = "角色列表")
  public PageResult<RoleGetListRes> getPage(@ParameterObject RoleGetListReq req) {
    return req.execute(req.getName(), req.toPageV0(), roleService);
  }

  @PostMapping("/permissions")
  @Operation(summary = "赋予角色权限")
  public void setPermissionsToRole(@RequestBody @Validated RolePermissionAddReq req) {
    req.getPermissionIds()
        .forEach(
            x ->
                rolePermissionService.insert(
                    RolePermission.builder().permissionId(x).roleId(req.getRoleId()).build()));
  }

  @PostMapping("/{roleId}")
  @Operation(summary = "赋予user角色")
  public void setRoleToUser(@PathVariable Integer roleId) {
    User user = UserContext.get();
    tokenService.saveUserRole(user.getId(), roleId);
    userRoleService.insert(UserRole.builder().userId(user.getId()).roleId(roleId).build());
  }
}
